package com.nexus.core.service.dto;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.beans.Transient;
import java.util.ArrayList;
import java.util.List;

/**
 * 树形结构实体基类 - 支持无限级树形结构
 *
 * @param <T> 实体类型
 * @Date 2025/7/23 15:35
 * @Author luzhengning
 **/
@Data
@EqualsAndHashCode(callSuper = false)
public abstract class TreeDTO<T extends TreeDTO<T>> extends BaseDTO {

    /**
     * 节点名称
     *
     * @Date 2025/7/23 15:47
     * @Author luzhengning
     **/
    protected String name;
    /**
     * 父节点对象
     *
     * @Date 2025/7/23 15:55
     * @Author luzhengning
     **/
    // 避免JSON序列化循环引用
    @JsonIgnore
    protected T parent;

    /**
     * 所有父级节点
     * @Date 2025/7/29 11:07
     * @Author luzhengning
     **/
    protected String parentIds;
    /**
     * 子节点列表 - 非数据库字段
     *
     * @Date 2025/7/23 15:55
     * @Author luzhengning
     **/
    @JsonInclude(JsonInclude.Include.NON_EMPTY) // 空集合时不序列化
    protected List<T> children = new ArrayList<>();

    /**
     * 排序字段
     *
     * @Date 2025/7/23 15:55
     * @Author luzhengning
     **/
    protected Integer sort = 0;
    /**
     * 层级深度
     *
     * @Date 2025/7/23 15:55
     * @Author luzhengning
     **/
    protected Integer level = 0;

    public TreeDTO() {
    }

    public TreeDTO(String id) {
        super(id);
    }

    /**
     * 添加子节点 (双向关联)
     *
     * @param child 子节点
     * @Date 2025/7/23 15:55
     * @Author luzhengning
     **/
    public void addChild(T child) {
        if (child == null) return;
        if (children == null) {
            children = new ArrayList<>();
        }
        children.add(child);
        child.setParent((T) this);
    }

    /**
     * 是否是根节点
     *
     * @Date 2025/7/23 15:56
     * @Author luzhengning
     **/
    @Transient
    @JsonProperty("isRoot") // JSON序列化字段
    public boolean isRoot() {
        return parent == null;
    }

    /**
     * 是否是叶子节点
     *
     * @Date 2025/7/23 15:56
     * @Author luzhengning
     **/
    @Transient
    @JsonProperty("isLeaf")
    public boolean isLeaf() {
        return children == null || children.isEmpty();
    }

    /**
     * 构建树路径
     *
     * @Date 2025/7/23 15:56
     * @Author luzhengning
     **/
    public void buildTreePath() throws Exception {
        if (this.isRoot()) {
            parentIds = "0";
            level = 0;
        } else if (parent != null) {
            if (ObjectUtils.isEmpty(parent.getId())) {
                throw new Exception("父级ID不能为空");
            }
            parentIds = parent.getParentIds() + parent.getId() + "/";
            level = parent.getLevel() + 1;
        }
    }
}
